package GUI;

import generator.MapGenerator;

import java.awt.AWTKeyStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.event.*;
import java.util.HashSet;
import java.util.Set;

import javax.swing.*;

import utilities.RefreshListener;

import controller.LocalManager;

import map.Map;
import map.Resolution;
import map.Texture;

public class GamePanel extends JPanel implements RefreshListener{
	public GamePanel(JFrame parent, boolean load, Dimension initialPreferredSize){
		this.setLayout(new BorderLayout());
		this.setPreferredSize(initialPreferredSize);
		parent.setFocusable(true);
		parent.addKeyListener(new MapKeyListener());
		curriculum = null;
		inventory = null;
		currentRes = Resolution.MID;
		//create new map
		if(!load){
			Map m = MapGenerator.next(24, 30);
			LocalManager.setMap(m);
			LocalManager.setCurrentMission(null); //it will be (re)created
			// set player location
			int i=0, j=0;
			boolean trovato = false;
			for(i = 0; i<m.getWidth() && !trovato; i++)
				for(j = 0; j<m.getHeight() && !trovato; j++)
					if(m.getTexture(i, j) == Texture.CITY)
						trovato = true;
			if(trovato)
				LocalManager.setPlayerLocation(new Point(i-1, j-1));
			else
				LocalManager.setPlayerLocation(new Point(m.getWidth()/2, m.getHeight()/2));
		}
		map = new MapPanel(currentRes);
		map.addMouseWheelListener(new MouseWheel());
		
		//create panel mission and other gui
		mission = new MissionPanel(currentRes, this, parent);
		mission.addMouseWheelListener(new MouseWheel());
		createOverlayButtonsPanel();
		createMapAndMission();
		refreshMapAndMissionPanel();
	}
	
	public void createOverlayButtonsPanel(){
		JPanel southPanel = new JPanel();
		southPanel.setOpaque(false);
		southPanel.setLayout(new BoxLayout(southPanel, BoxLayout.X_AXIS));
		southPanel.setPreferredSize(new Dimension(getWidth(), 50));
		JButton curr = new JButton("Curriculum");
		curr.addActionListener(new CurriculumListener());
		JButton inv = new JButton("Inventario");
		inv.addActionListener(new InventoryListener());
		
		southPanel.add(Box.createHorizontalGlue());
		southPanel.add(inv);
		southPanel.add(Box.createRigidArea(new Dimension(10, 0)));
		southPanel.add(curr);
		
		overlayedPanel = new JPanel(new BorderLayout());
		overlayedPanel.add(southPanel, BorderLayout.SOUTH);
		overlayedPanel.setOpaque(false);
	}
	
	public void createMapAndMission(){
		Dimension size = map.getPreferredSize();
		JLayeredPane mapAndMissionLayer = new JLayeredPane();
		mapAndMissionLayer.setOpaque(false);
		mapAndMissionLayer.setPreferredSize(size);
		map.setBounds(0, 0, size.width, size.height);
		mapAndMissionLayer.add(map, JLayeredPane.DEFAULT_LAYER);
		if(mission != null){
			mission.setBounds(0, 0, size.width, size.height);
			mapAndMissionLayer.add(mission, JLayeredPane.PALETTE_LAYER);
		}
		
		mapAndMission = new JPanel();
		mapAndMission.setBackground(new Color(205, 220, 255));
		mapAndMission.setOpaque(true);
		mapAndMission.add(mapAndMissionLayer);
	}
	
	public void refreshMapAndMissionPanel(){
		this.refreshMapAndMissionPanel(1.0, null);
	}
	
	public void refreshMapAndMissionPanel(double scaledFactor, Point centerPoint){
		Point point = new Point(0,0);
		if(scroll != null){
			point = scroll.getViewport().getViewPosition();
		}
		scroll = new JScrollPane(mapAndMission);
		if(centerPoint != null){
			int offX = (int)(centerPoint.x * scaledFactor) - centerPoint.x;
		    int offY = (int)(centerPoint.y * scaledFactor) - centerPoint.y;
		    scroll.getViewport().setViewPosition(new Point(point.x+offX, point.y+offY));
		}else
			scroll.getViewport().setViewPosition(point);
		
	    if(centerPanel != null){
			this.remove(centerPanel);
		}
	    centerPanel = new JLayeredPane();
	    centerPanel.setOpaque(false);
	    
	    replacePanels();
	    centerPanel.add(scroll, JLayeredPane.DEFAULT_LAYER);
	    centerPanel.add(overlayedPanel, JLayeredPane.PALETTE_LAYER);
		this.add(centerPanel, BorderLayout.CENTER);
		this.revalidate();
	}
	
	public void replacePanels(){
		Dimension globalSize = this.getPreferredSize();
		int w = globalSize.width;
		if(curriculum!= null){
			w -= curriculum.getPreferredSize().width;
		}
		if(inventory != null){
			w -= inventory.getPreferredSize().width;
		}
		
		if(overlayedPanel != null){
			overlayedPanel.setBounds(10, 0, w-60, globalSize.height-35);
		}
		if(scroll != null && centerPanel != null){
			centerPanel.setPreferredSize(new Dimension(w, globalSize.height));
		    scroll.setBounds(0, 0, w, globalSize.height);
		}
	}
	
	@Override
	public void refresh() {
		if(curriculum != null){
			curriculum.checkUnspentPoints();
			curriculum.updateValues();
		}
		if(inventory != null){
			inventory.updateValues();
		}
		refreshMapAndMissionPanel();
	}
	
	@Override
	public void setPreferredSize(Dimension preferredSize) {
		super.setPreferredSize(preferredSize);
		if(map!= null)
			refreshMapAndMissionPanel();
	}
	
	@Override
	public Set<AWTKeyStroke> getFocusTraversalKeys (int id) {
		if (id==KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS ||
		    id==KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS) {
		  return new HashSet<AWTKeyStroke>();
		} else return super.getFocusTraversalKeys(id);
	}
	
	class CurriculumListener implements ActionListener{
        public void actionPerformed(ActionEvent e) {
        	if(curriculum == null){
	        	curriculum = new CurriculumPG(GamePanel.this);
	        	add(curriculum, BorderLayout.EAST);
        	}else{
        		remove(curriculum);
        		curriculum = null;
        	}
        	replacePanels();
    		revalidate();
        }
    }

    class InventoryListener implements ActionListener{
        public void actionPerformed(ActionEvent e) {
        	if(inventory == null){
        		inventory = new Inventory(GamePanel.this);
	        	add(inventory, BorderLayout.WEST);
        	}else{
        		remove(inventory);
        		inventory = null;
        	}
        	replacePanels();
    		revalidate();
        }
    }
	
	class MouseWheel implements MouseWheelListener{
		public void mouseWheelMoved(MouseWheelEvent e) {
			int n = e.getWheelRotation();
			int res = currentRes.ordinal();
			double scaledFactor = 1;
			if(n > 0){
				if(res>0){
					res--;
					scaledFactor=(double)(currentRes.getFactor()-25)/currentRes.getFactor();
				}
			}else{
				if(res < (Resolution.values().length-1)){
					res++;
					scaledFactor=(double)(currentRes.getFactor()+25)/currentRes.getFactor();
				}
			}
			currentRes = Resolution.values()[res];
			map.setResolution(currentRes);
			if(mission != null)
				mission.setResolution(currentRes);
			createMapAndMission();
			refreshMapAndMissionPanel(scaledFactor, e.getPoint());
		}
	}
    
    class MapKeyListener implements KeyListener{
		public void keyPressed(KeyEvent e) {
			Point p = LocalManager.getPlayerLocation();
			switch(e.getKeyCode()){
			case KeyEvent.VK_ESCAPE:
				break;
			case KeyEvent.VK_I:
				new InventoryListener().actionPerformed(null);
				break;
			case KeyEvent.VK_C:
				new CurriculumListener().actionPerformed(null);
				break;
			case KeyEvent.VK_LEFT:
				LocalManager.setPlayerLocation(new Point(p.x-1, p.y));
				mission.refreshPanel();
				break;
			case KeyEvent.VK_RIGHT:
				LocalManager.setPlayerLocation(new Point(p.x+1, p.y));
				mission.refreshPanel();
				break;
			case KeyEvent.VK_UP:
				LocalManager.setPlayerLocation(new Point(p.x, p.y-1));
				mission.refreshPanel();
				break;
			case KeyEvent.VK_DOWN:
				LocalManager.setPlayerLocation(new Point(p.x, p.y+1));
				mission.refreshPanel();
				break;
			}
		}
		public void keyReleased(KeyEvent e) {
			// TODO Auto-generated method stub
			
		}
		public void keyTyped(KeyEvent e) {
			// TODO Auto-generated method stub
			
		}
    }
	
	private JPanel overlayedPanel, mapAndMission;
	private CurriculumPG curriculum;
	private Inventory inventory;
	private MapPanel map;
	private MissionPanel mission;
	private JScrollPane scroll;
	private JLayeredPane centerPanel;
	private Resolution currentRes;
	private static final long serialVersionUID = 5426650005652L;
}
